package org.simp.service;
/**
 *@author  zhuhaitao at 2014-6-5
 * 
 **/
public  abstract class BaseRunnableService implements Runnable {

	protected boolean isRun;
	
	protected boolean state;
	private final Object lock = new Object();
	
	private Object initLock = new Object();
	private boolean inited ;
	
	protected Thread thread;
	@Override
	public void run() {
		isRun = true;
		state = true;
		init();
		inited= true;
		while(isRun){
			alwaysRun();
			try {
				Thread.sleep(getPeriod()*1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		destroy();
		state = false;
	}
	/**
	 * 线程运行的周期，时间间隔(s)
	 * @return
	 * @author zhuhaitao at 2014-6-5
	 */
	protected abstract long getPeriod() ;

	public abstract void init();
	
	public abstract void alwaysRun();
	
	public abstract void destroy();
	
	public synchronized void start(){
		if(isRun){
			return;
		}
		thread = new Thread(this);
		thread.setName(getClass().getSimpleName());
		thread.start();
	}
	
	public synchronized void stop(){
		isRun = false;
	}

	public void restart(){
		if(thread == null){
			start();
		}else{
			if(awaitStopUninterruptibly()){
				start();
			}
		}
	}
	/**
	 * 等待线程结束，如果线程结束，返回true，最多等待60s
	 * @return
	 * @author zhuhaitao at 2014-6-5
	 */
	public boolean awaitStopUninterruptibly(){
		int wait =0;
		if(thread == null){
			return true;
		}
		while(state){
			
			try{
				synchronized (lock) {
					if(wait >60){
						break;
					}
					wait ++;
					lock.wait(1000);
				}
				
			}catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		return !state;
	}

	public boolean awaitInit(){
		int count =0;
		while(!inited){
			synchronized (initLock) {
				try {
					initLock.wait(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				count++;
				if(count >=60){
					return false;
				}
			}
		}
		return true;
	}
	public Thread getThread() {
		return thread;
	}
	
}
